package dd.prog2.musterExercises.ws12set12;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

import dd.prog2.musterExercises.ws12set01_connectfour.Disk;
import dd.prog2.musterExercises.ws12set01_connectfour.Game;

/**
 * Provides a simple GUI for the Connect Four game. Here, grid spaces are
 * represented by extended buttons which know their position and use 2d graphics
 * to visualize disks. A central action listener - realized as inner class - is
 * used.
 * 
 * @author Ruediger Lunde
 * 
 */
public class ConnectFourAppV2 {

	// create attributes for all parts of the application which need to be
	// accessed by listeners, inner classes, and helper methods

	private JFrame frame;
	private JButton clearButton;
	private JPanel boardPanel;
	private JLabel statusBar;

	private Game game;

	/** Creates a game object, constructs the game frame and makes it visible. */
	public void start() {
		game = new Game();

		frame = new JFrame("Connect Four V2");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		AppActionListener listener = new AppActionListener();
		clearButton = new JButton("Clear");
		clearButton.addActionListener(listener);
		frame.add(clearButton, BorderLayout.NORTH);
		int rows = game.getBoard().getRows();
		int cols = game.getBoard().getCols();
		boardPanel = new JPanel();
		boardPanel.setLayout(new GridLayout(rows, cols, 5, 5));
		boardPanel.setBorder(BorderFactory.createEtchedBorder());
		boardPanel.setBackground(Color.BLUE);
		for (int i = 0; i < rows * cols; i++) {
			GridElement element = new GridElement(i / cols, i % cols);
			boardPanel.add(element);
			element.addActionListener(listener);
		}
		frame.add(boardPanel, BorderLayout.CENTER);
		statusBar = new JLabel();
		frame.getContentPane().setBackground(Color.BLUE);
		statusBar.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
		frame.add(statusBar, BorderLayout.SOUTH);

		updateStatus();
		frame.setSize(400, 400);
		frame.setVisible(true);
	}

	/** Updates the status bar. */
	private void updateStatus() {
		if (!game.isGameOver()) {
			String toMove = game.getNextPlayerColor();
			statusBar.setText("Next move: " + toMove);
			statusBar.setForeground(toMove.equals("red") ? Color.RED
					: Color.YELLOW);
		} else if (game.getWinner() != null){
			statusBar.setText("Color " + game.getWinner() + " has won. Congratulations!");
			statusBar.setForeground(Color.WHITE);
		} else {
			statusBar.setText("No winner :-(");
		}
	}

	/** Creates the Connect Four Application and starts it. */
	public static void main(String[] args) {
		ConnectFourAppV2 gameApp = new ConnectFourAppV2();
		gameApp.start();
	}

	// //////////////////////////////////////////////////////////////
	// inner classes

	private class AppActionListener implements ActionListener {
		/** Defines the reactions on grid element events. */
		@Override
		public void actionPerformed(ActionEvent e) {
			if (e.getSource() == clearButton) {
				game = new Game(); // start a new game
			} else if (!game.isGameOver()
					&& e.getSource() instanceof GridElement) {
				GridElement el = (GridElement) e.getSource();
				game.makeMove(el.col); // make next move
			}
			boardPanel.repaint(); // paint all disks!
			updateStatus();
		}
	}

	/** Represents a space within the grid where discs can be placed. */
	@SuppressWarnings("serial")
	private class GridElement extends JButton {
		int row;
		int col;

		GridElement(int row, int col) {
			this.row = row;
			this.col = col;
			setBackground(Color.BLUE);
		}

		/** Draws a simple oval. */
		void drawDisk(Graphics g, Disk disk) {
			g.setColor(disk.getColor().equals("red") ? Color.RED : Color.YELLOW);
			g.fillOval(0, 0, getWidth(), getHeight());
		}

		public void paintComponent(Graphics g) {
			super.paintComponent(g); // should have look and feel of a button...
			Disk disk = game.getBoard().getDiskAt(row, col);
			if (disk != null) {
				drawDisk(g, disk); // draw disk on top!
			}
		}
	}
}
